package com.fy.restfulapi.advice;

import com.alibaba.fastjson.JSON;
import com.fy.restfulapi.annotation.IgnoreUnifiedRESTful;
import com.fy.restfulapi.config.RestApiGlobalDefaultProperties;
import com.fy.restfulapi.response.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author sunlei
 */
@Slf4j
@RestControllerAdvice
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class GlobalResponseDataAdvice implements ResponseBodyAdvice<Object> {

    private final RestApiGlobalDefaultProperties globalDefaultProperties;

    public GlobalResponseDataAdvice(RestApiGlobalDefaultProperties globalDefaultProperties) {
        this.globalDefaultProperties = globalDefaultProperties;
    }

    /**
     * supports方法: 判断是否要执行beforeBodyWrite方法,
     * true为执行,false不执行.
     * 通过该方法可以选择哪些类或那些方法的response要进行处理, 其他的不进行处理.
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
//        log.info("+++++++++——————————MethodParameter：" + returnType.toString());
        return filter(returnType);
    }

    /**
     * beforeBodyWrite方法: 对response方法进行具体操作处理
     * 实际返回结果业务包装处理
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body == null) {
            // // 当 body 返回类型为 string 并且值为null时，就会抛出类型转换异常 java.lang.ClassCastException: Result cannot be cast to java.lang.String
            if (returnType.getParameterType().getName().equals("java.lang.String")) {
                /**
                 * 这样做的话，data字段就不会返回了，不过不影响使用
                 * 例如：{"code":200,"success":true,"message":"请求成功","timestamp":1689229403889}
                 */
                return JSON.toJSON(R.success()).toString();
            }
            return R.success();
        }

        if (body instanceof R) {
            return body;
        }

        // string 特殊处理 java.lang.ClassCastException: Result cannot be cast to java.lang.String
        if (body instanceof String) {
            return JSON.toJSON(R.success().data(body)).toString();
        }

        return R.success().data(body);
    }

    private Boolean filter(MethodParameter methodParameter) {
        Class<?> declaringClass = methodParameter.getDeclaringClass();
//        log.info("+++++++++++____________" + declaringClass.toString() + "  是否使用注解：" + methodParameter.getMethod().isAnnotationPresent(IgnoreUnifiedRESTful.class));
        // 检查过滤包路径
        long count = globalDefaultProperties.getAdviceFilterPackage().stream()
                .filter(l -> declaringClass.getName().contains(l)).count();
        if (count > 0) {
            return false;
        }
        // 检查<类>过滤列表
        if (globalDefaultProperties.getAdviceFilterClass().contains(declaringClass.getName())) {
            return false;
        }
        // 检查类中是否有IgnoreUnifiedRESTful注解
        if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreUnifiedRESTful.class)) {
            return false;
        }
        // 检查方法中是否有IgnoreUnifiedRESTful注解
        if (methodParameter.getMethod().isAnnotationPresent(IgnoreUnifiedRESTful.class)) {
            return false;
        }
        return true;
    }
}
